package com.lzq.chatroom_project.controller;

import com.lzq.chatroom_project.common.utils.CacheUtil;
import com.lzq.chatroom_project.common.utils.JacksonUtil;
import com.lzq.chatroom_project.dao.MessageMapper;
import com.lzq.chatroom_project.dao.MessageSessionMapper;
import com.lzq.chatroom_project.model.*;
import com.lzq.chatroom_project.service.BitmapService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import static com.lzq.chatroom_project.common.constants.CacheKeyConstants.FRIEND_LIST_KEY_PREFIX;
import static com.lzq.chatroom_project.common.constants.CacheKeyConstants.FRIEND_LIST_KEY_SUFFIX;


@Slf4j
@Component
public class WebSocketController extends TextWebSocketHandler {

    @Autowired
    private OnlineUserManager onlineUserManager;
    @Autowired
    private MessageSessionMapper messageSessionMapper;
    @Autowired
    private CacheUtil cacheUtil;
    @Autowired
    private MessageMapper messageMapper;
    @Autowired
    private SensitiveWordTrie sensitiveWordTrie;
    @Autowired
    private BitmapService bitmapService;

    /**
     * webSocketSession成功连接
     * @param session
     * @throws Exception
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        log.info("websocket连接成功!");
        User user = (User) session.getAttributes().get("user");
        onlineUserManager.online(user.getUserId(), session);
    }

    /**
     * webSocketSession成功接受文本信息
     * @param session
     * @throws Exception
     */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        log.info("websocket收到消息:{}!",message);
        User user = (User) session.getAttributes().get("user");
        //使用objectMapper读取message的信息为MessageRequest的实例
        MessageRequest req = JacksonUtil.readValue(message.getPayload(),MessageRequest.class);
        //校验message的类型
        if ("switchKey".equals(req.getType())) {
            handleMessage(user, req);
        }
    }

    /**
     * webSocketSession连接异常
     * @param session
     * @param exception
     * @throws Exception
     */
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        log.error("websocket连接异常:{}!",exception);
        User user = (User) session.getAttributes().get("user");
        onlineUserManager.offline(user.getUserId(), session);
    }

    /**
     * webSocketSession连接关闭
     * @param session
     * @param status
     * @throws Exception
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        log.info("websocket连接关闭!");
        User user = (User) session.getAttributes().get("user");
        onlineUserManager.offline(user.getUserId(), session);
    }

    /**
     * 处理文本消息
     * @param fromUser
     * @param req
     * @throws IOException
     */
    private void handleMessage(User fromUser,MessageRequest req) throws IOException {
        //设置resp对象属性
        MessageResponse resp = new MessageResponse();
        resp.setType("switchKey");
        resp.setFromId(fromUser.getUserId());
        resp.setFromName(fromUser.getUsername());
        resp.setSessionId(req.getSessionId());
        resp.setContent(sensitiveWordTrie.filter(req.getContent()));
        LocalDateTime date = LocalDateTime.now();
        resp.setPostTime(date);
        //将resp对象写为字符串传输
        String respJson = JacksonUtil.writeValueAsString(resp);
        log.info("resp:{}", respJson);
        //根据sessionId查询对应session的好友列表
        Integer sessionId = req.getSessionId();
        Integer userId = fromUser.getUserId();

        if (!bitmapService.hasMessagesOnDate(sessionId, userId, LocalDate.now())) {
            bitmapService.markMessagePosted(sessionId, userId, LocalDate.now());
        }

        String cacheKey = FRIEND_LIST_KEY_PREFIX+sessionId+FRIEND_LIST_KEY_SUFFIX+userId;
        List<Friend> friendList = null;
        if (cacheUtil.hasKey(cacheKey)) {
            friendList = JacksonUtil.readListValue(cacheUtil.get(cacheKey), Friend.class);
        } else {
            friendList = messageSessionMapper.queryFriendsBySessionId(sessionId, userId);
            cacheUtil.set(cacheKey, JacksonUtil.writeValueAsString(friendList));
        }
        //自己也是消息传输的对象
        Friend myself = new Friend();
        myself.setFriendId(fromUser.getUserId());
        myself.setFriendName(fromUser.getUsername());
        friendList.add(myself);
        log.info("转发给:{}",friendList);
        for (Friend friend : friendList) {
            WebSocketSession webSocketSession = onlineUserManager.getSession(friend.getFriendId());
            if (webSocketSession == null) {
                continue;
            }
            //发送消息,resp再传入构造TextMessage的实例
            webSocketSession.sendMessage(new TextMessage(respJson));
        }
        //设置message并插入数据库
        Message message = new Message();
        message.setMessageId(UUID.randomUUID().timestamp());
        message.setFromId(resp.getFromId());
        message.setSessionId(resp.getSessionId());
        message.setContent(resp.getContent());
        message.setPostTime(date);
        messageMapper.add(message);
    }
}
